fix(nemo-relay): bound dependency, migrate intercept API, fix concurrent scopes - #58
Merged
Merged
Conversation
…ent scopes The nemo-relay dependency was unbounded (>=0.4.0), so downstream installs got 0.6.0 while the lock pinned 0.4.0 and CI only ever tested 0.4.0. The intercept contract changed in 0.5 (LLMRequestInterceptOutcome instead of a tuple), so the quickstart example was broken for anyone installing today. Separately, nemo-relay keeps one mutable LIFO scope stack in a ContextVar that child asyncio tasks inherit by reference. Overlapping agent calls interleaved their pushes; whichever finished first could not pop, silently desynchronising the stack, misattributing ATIF ancestry, and raising RuntimeError out of nemo_flow_scope after the agent had already produced its result. A concurrently-dispatched call now gets its own scope stack, with parent linkage preserved via scope.push(handle=...). - pin nemo-relay>=0.6,<0.7 (0.7 changes the LLM sanitizer contract) - migrate intercepts to LLMRequestInterceptOutcome - isolate scope stacks for concurrent agent calls; log pop failures at warning - add 4 concurrency regression tests (the file had none) - clean up the quickstart example and correct two false comments Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The upstream package was renamed nemo_flow -> nemo_relay some time ago, but nooa's own API kept the old prefix and the module aliased the import back to `nemo_flow`. Cleaning up the quickstart made the split visible: the example referred to `nemo_relay` for the upstream package while still importing `nemo_flow_scope` from nooa. BREAKING CHANGE: no compatibility aliases are provided. nooa.nemo_flow_middleware -> nooa.nemo_relay_middleware nemo_flow_scope -> nemo_relay_scope install_nemo_flow -> install_nemo_relay nemo_flow_llm_middleware -> nemo_relay_llm_middleware nemo_flow_tool_middleware -> nemo_relay_tool_middleware nemo_flow_agent_call_middleware-> nemo_relay_agent_call_middleware Also drops the now-meaningless rename-era comments and the `import nemo_relay as nemo_flow` alias, and renames the two test modules to match. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…oject The first pass matched only snake_case (\bnemo_flow\b) and was scoped to *.py/*.md under src/tests/examples/skills, so it missed: - 11 CamelCase test classes (TestNemoFlow* -> TestNemoRelay*) - two .gitignore comments (file type not searched) - the pyproject extra's header, including a now-obsolete note that the upstream package "was renamed from nemo-flow to nemo-relay" Verified with an unfiltered `git grep -inE "nemo[-_ ]?flow"` over all tracked files: zero matches. Remaining occurrences of "flow" are ordinary English (event flow, control flow, OAuth flow). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
refactor(nemo-relay)!: rename nemo_flow_* to nemo_relay_*
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
nemo-relaywas unbounded (>=0.4.0), so fresh installs got 0.6.0 while the lock pinned 0.4.0 — and the intercept contract changed in 0.5, leaving the quickstart broken for anyone installing today.While verifying, found a second bug: nemo-relay keeps one mutable LIFO scope stack that child asyncio tasks inherit by reference. Overlapping agent calls interleave pushes, the first to finish can't pop, and the run raises
RuntimeErrorout ofnemo_flow_scopeafter already producing its result. Reachable viaasyncio.gather(self.a(), self.b()), which our own strategy prompts recommend.Changes
nemo-relay>=0.6,<0.7— 0.7 changes the LLM sanitizer contract with no compat shimLLMRequestInterceptOutcomescope.push(handle=...); pop failures now log atwarninginstead of being swallowedVerification
RuntimeErrorparent_idsFull suite 6479 passed. Quickstart re-run clean, ATIF inspected.
Note
Scope isolation relies on
nemo_relay._scope_stack_var, which is private upstream. Resolved viagetattrwith graceful degradation, plus a test that fails loudly if it's renamed. Worth raising with the NeMo Relay team — the real ask is a public API for per-task scope isolation.🤖 Generated with Claude Code